using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
using GamePlay.Framework.Events;

namespace GamePlay.Features.Audio
{
    /// <summary>
    /// 音频管理器，负责游戏中的音乐和音效播放
    /// </summary>
    public class AudioManager : MonoBehaviour
    {
        #region 单例实现

        private static AudioManager _instance;

        public static AudioManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    GameObject obj = new GameObject("AudioManager");
                    _instance = obj.AddComponent<AudioManager>();
                    DontDestroyOnLoad(obj);
                }
                return _instance;
            }
        }

        private void Awake()
        {
            if (_instance != null && _instance != this)
            {
                Destroy(gameObject);
                return;
            }

            _instance = this;
            DontDestroyOnLoad(gameObject);

            // 初始化音频池
            InitializeAudioPool();

            // 从PlayerPrefs加载音频设置
            LoadSettings();
        }

        #endregion

        #region 字段和属性

        [Header("音频设置")]
        [SerializeField] private AudioMixer _audioMixer;
        [SerializeField] private string _masterVolumeParam = "MasterVolume";
        [SerializeField] private string _musicVolumeParam = "MusicVolume";
        [SerializeField] private string _sfxVolumeParam = "SFXVolume";

        [Header("音频源")]
        [SerializeField] private AudioSource _musicSource;
        [SerializeField] private int _sfxSourceCount = 5;

        [Header("淡入淡出设置")]
        [SerializeField] private float _fadeInDuration = 1.0f;
        [SerializeField] private float _fadeOutDuration = 1.0f;

        [Header("调试设置")]
        [SerializeField] private bool _debugMode = false;

        // 音频源池
        private List<AudioSource> _sfxSources = new List<AudioSource>();

        // 当前音乐
        private AudioClip _currentMusic;

        // 音频剪辑缓存
        private Dictionary<string, AudioClip> _audioCache = new Dictionary<string, AudioClip>();

        // 设置
        private float _masterVolume = 1.0f;
        private float _musicVolume = 1.0f;
        private float _sfxVolume = 1.0f;
        private bool _isMuted = false;

        // 淡入淡出协程
        private Coroutine _fadeCoroutine;

        // 常量
        private const string MASTER_VOLUME_KEY = "MasterVolume";
        private const string MUSIC_VOLUME_KEY = "MusicVolume";
        private const string SFX_VOLUME_KEY = "SFXVolume";
        private const string MUTED_KEY = "AudioMuted";

        // 属性
        public float MasterVolume
        {
            get => _masterVolume;
            set => SetMasterVolume(value);
        }

        public float MusicVolume
        {
            get => _musicVolume;
            set => SetMusicVolume(value);
        }

        public float SfxVolume
        {
            get => _sfxVolume;
            set => SetSfxVolume(value);
        }

        public bool IsMuted
        {
            get => _isMuted;
            set => SetMuted(value);
        }

        public AudioClip CurrentMusic => _currentMusic;

        #endregion

        #region 初始化

        /// <summary>
        /// 初始化音频源池
        /// </summary>
        private void InitializeAudioPool()
        {
            // 如果没有设置音乐源，创建一个
            if (_musicSource == null)
            {
                GameObject musicObj = new GameObject("MusicSource");
                musicObj.transform.parent = transform;
                _musicSource = musicObj.AddComponent<AudioSource>();
                _musicSource.loop = true;
                _musicSource.playOnAwake = false;
            }

            // 创建音效源池
            for (int i = 0; i < _sfxSourceCount; i++)
            {
                GameObject sfxObj = new GameObject($"SFXSource_{i}");
                sfxObj.transform.parent = transform;
                AudioSource source = sfxObj.AddComponent<AudioSource>();
                source.playOnAwake = false;
                _sfxSources.Add(source);
            }

            Log($"音频源池已初始化: 音乐源 x1, 音效源 x{_sfxSourceCount}");
        }

        /// <summary>
        /// 加载音频设置
        /// </summary>
        private void LoadSettings()
        {
            _masterVolume = PlayerPrefs.GetFloat(MASTER_VOLUME_KEY, 1.0f);
            _musicVolume = PlayerPrefs.GetFloat(MUSIC_VOLUME_KEY, 1.0f);
            _sfxVolume = PlayerPrefs.GetFloat(SFX_VOLUME_KEY, 1.0f);
            _isMuted = PlayerPrefs.GetInt(MUTED_KEY, 0) == 1;

            // 应用设置到音频混合器
            if (_audioMixer != null)
            {
                ApplyVolumeToMixer();
            }

            Log("音频设置已加载");
        }

        /// <summary>
        /// 保存音频设置
        /// </summary>
        private void SaveSettings()
        {
            PlayerPrefs.SetFloat(MASTER_VOLUME_KEY, _masterVolume);
            PlayerPrefs.SetFloat(MUSIC_VOLUME_KEY, _musicVolume);
            PlayerPrefs.SetFloat(SFX_VOLUME_KEY, _sfxVolume);
            PlayerPrefs.SetInt(MUTED_KEY, _isMuted ? 1 : 0);
            PlayerPrefs.Save();

            Log("音频设置已保存");
        }

        #endregion

        #region 公共方法 - 播放

        /// <summary>
        /// 播放背景音乐
        /// </summary>
        /// <param name="clipName">音频剪辑名称</param>
        /// <param name="fadeIn">是否淡入</param>
        public void PlayMusic(string clipName, bool fadeIn = true)
        {
            StartCoroutine(PlayMusicRoutine(clipName, fadeIn));
        }

        /// <summary>
        /// 播放音效
        /// </summary>
        /// <param name="clipName">音频剪辑名称</param>
        /// <param name="volume">音量（0-1）</param>
        /// <param name="pitch">音调（0.5-2）</param>
        /// <returns>音频源，可用于进一步控制</returns>
        public AudioSource PlaySFX(string clipName, float volume = 1.0f, float pitch = 1.0f)
        {
            AudioClip clip = GetAudioClip(clipName);
            if (clip == null)
            {
                LogWarning($"找不到音效: {clipName}");
                return null;
            }

            // 获取可用的音频源
            AudioSource source = GetAvailableSFXSource();
            if (source == null)
            {
                LogWarning("没有可用的音效源");
                return null;
            }

            // 设置音频源属性
            source.clip = clip;
            source.volume = volume * _sfxVolume * _masterVolume;
            source.pitch = pitch;
            source.loop = false;

            // 播放音效
            source.Play();

            if (_debugMode)
            {
                Log($"播放音效: {clipName}, 音量: {source.volume}");
            }

            return source;
        }

        /// <summary>
        /// 在特定位置播放3D音效
        /// </summary>
        /// <param name="clipName">音频剪辑名称</param>
        /// <param name="position">世界坐标位置</param>
        /// <param name="volume">音量（0-1）</param>
        /// <param name="pitch">音调（0.5-2）</param>
        /// <param name="minDistance">最小距离</param>
        /// <param name="maxDistance">最大距离</param>
        /// <returns>音频源，可用于进一步控制</returns>
        public AudioSource PlaySFXAtPosition(string clipName, Vector3 position, float volume = 1.0f, float pitch = 1.0f, float minDistance = 1.0f, float maxDistance = 50.0f)
        {
            AudioClip clip = GetAudioClip(clipName);
            if (clip == null)
            {
                LogWarning($"找不到音效: {clipName}");
                return null;
            }

            // 获取可用的音频源
            AudioSource source = GetAvailableSFXSource();
            if (source == null)
            {
                LogWarning("没有可用的音效源");
                return null;
            }

            // 设置位置
            source.gameObject.transform.position = position;

            // 设置3D音频属性
            source.spatialBlend = 1.0f; // 完全3D
            source.minDistance = minDistance;
            source.maxDistance = maxDistance;

            // 设置音频源属性
            source.clip = clip;
            source.volume = volume * _sfxVolume * _masterVolume;
            source.pitch = pitch;
            source.loop = false;

            // 播放音效
            source.Play();

            if (_debugMode)
            {
                Log($"在位置 {position} 播放3D音效: {clipName}");
            }

            return source;
        }

        /// <summary>
        /// 播放循环音效
        /// </summary>
        /// <param name="clipName">音频剪辑名称</param>
        /// <param name="volume">音量（0-1）</param>
        /// <param name="pitch">音调（0.5-2）</param>
        /// <returns>音频源，可用于停止循环</returns>
        public AudioSource PlayLoopingSFX(string clipName, float volume = 1.0f, float pitch = 1.0f)
        {
            AudioClip clip = GetAudioClip(clipName);
            if (clip == null)
            {
                LogWarning($"找不到音效: {clipName}");
                return null;
            }

            // 获取可用的音频源
            AudioSource source = GetAvailableSFXSource();
            if (source == null)
            {
                LogWarning("没有可用的音效源");
                return null;
            }

            // 设置音频源属性
            source.clip = clip;
            source.volume = volume * _sfxVolume * _masterVolume;
            source.pitch = pitch;
            source.loop = true;

            // 播放音效
            source.Play();

            if (_debugMode)
            {
                Log($"播放循环音效: {clipName}");
            }

            return source;
        }

        #endregion

        #region 公共方法 - 控制

        /// <summary>
        /// 停止背景音乐
        /// </summary>
        /// <param name="fadeOut">是否淡出</param>
        public void StopMusic(bool fadeOut = true)
        {
            if (fadeOut && _musicSource.isPlaying)
            {
                StartFade(FadeType.Out);
            }
            else
            {
                _musicSource.Stop();
                _currentMusic = null;
            }

            Log("停止背景音乐");
        }

        /// <summary>
        /// 暂停背景音乐
        /// </summary>
        public void PauseMusic()
        {
            if (_musicSource.isPlaying)
            {
                _musicSource.Pause();
                Log("暂停背景音乐");
            }
        }

        /// <summary>
        /// 恢复背景音乐
        /// </summary>
        public void ResumeMusic()
        {
            if (!_musicSource.isPlaying && _musicSource.clip != null)
            {
                _musicSource.UnPause();
                Log("恢复背景音乐");
            }
        }

        /// <summary>
        /// 停止特定音效
        /// </summary>
        /// <param name="source">音频源</param>
        public void StopSFX(AudioSource source)
        {
            if (source != null && _sfxSources.Contains(source))
            {
                source.Stop();
                Log($"停止音效: {source.clip?.name}");
            }
        }

        /// <summary>
        /// 停止所有音效
        /// </summary>
        public void StopAllSFX()
        {
            foreach (var source in _sfxSources)
            {
                source.Stop();
            }

            Log("停止所有音效");
        }

        /// <summary>
        /// 停止所有音频
        /// </summary>
        public void StopAll()
        {
            StopMusic(false);
            StopAllSFX();

            Log("停止所有音频");
        }

        #endregion

        #region 公共方法 - 设置

        /// <summary>
        /// 设置主音量
        /// </summary>
        /// <param name="volume">音量（0-1）</param>
        public void SetMasterVolume(float volume)
        {
            _masterVolume = Mathf.Clamp01(volume);
            ApplyVolumeToMixer();
            SaveSettings();

            Log($"设置主音量: {_masterVolume}");
        }

        /// <summary>
        /// 设置音乐音量
        /// </summary>
        /// <param name="volume">音量（0-1）</param>
        public void SetMusicVolume(float volume)
        {
            _musicVolume = Mathf.Clamp01(volume);
            ApplyVolumeToMixer();
            SaveSettings();

            Log($"设置音乐音量: {_musicVolume}");
        }

        /// <summary>
        /// 设置音效音量
        /// </summary>
        /// <param name="volume">音量（0-1）</param>
        public void SetSfxVolume(float volume)
        {
            _sfxVolume = Mathf.Clamp01(volume);
            ApplyVolumeToMixer();
            SaveSettings();

            Log($"设置音效音量: {_sfxVolume}");
        }

        /// <summary>
        /// 设置静音状态
        /// </summary>
        /// <param name="muted">是否静音</param>
        public void SetMuted(bool muted)
        {
            _isMuted = muted;
            ApplyVolumeToMixer();
            SaveSettings();

            Log($"设置静音: {_isMuted}");
        }

        /// <summary>
        /// 切换静音状态
        /// </summary>
        /// <returns>当前静音状态</returns>
        public bool ToggleMute()
        {
            _isMuted = !_isMuted;
            ApplyVolumeToMixer();
            SaveSettings();

            Log($"切换静音: {_isMuted}");
            return _isMuted;
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 加载音频剪辑
        /// </summary>
        private AudioClip GetAudioClip(string clipName)
        {
            // 检查缓存
            if (_audioCache.TryGetValue(clipName, out AudioClip clip))
            {
                return clip;
            }

            // 从Resources加载
            string path = "Audio/" + clipName;
            clip = Resources.Load<AudioClip>(path);

            if (clip != null)
            {
                // 添加到缓存
                _audioCache[clipName] = clip;
                return clip;
            }

            LogWarning($"无法加载音频剪辑: {clipName}");
            return null;
        }

        /// <summary>
        /// 获取可用的音效音频源
        /// </summary>
        private AudioSource GetAvailableSFXSource()
        {
            // 首先查找不在播放的音频源
            foreach (var source in _sfxSources)
            {
                if (!source.isPlaying)
                {
                    return source;
                }
            }

            // 如果所有源都在使用，使用播放时间最长的
            AudioSource oldestSource = null;
            float longestTime = 0;

            foreach (var source in _sfxSources)
            {
                float playTime = source.clip.length - source.time;
                if (oldestSource == null || playTime > longestTime)
                {
                    oldestSource = source;
                    longestTime = playTime;
                }
            }

            return oldestSource;
        }

        /// <summary>
        /// 应用音量设置到混音器
        /// </summary>
        private void ApplyVolumeToMixer()
        {
            if (_audioMixer == null)
                return;

            // 将音量值转换为分贝值
            float masterDb = _isMuted ? -80.0f : ConvertToDecibel(_masterVolume);
            float musicDb = ConvertToDecibel(_musicVolume);
            float sfxDb = ConvertToDecibel(_sfxVolume);

            // 应用到混音器
            _audioMixer.SetFloat(_masterVolumeParam, masterDb);
            _audioMixer.SetFloat(_musicVolumeParam, musicDb);
            _audioMixer.SetFloat(_sfxVolumeParam, sfxDb);

            // 如果没有使用混音器，直接设置音乐源的音量
            _musicSource.volume = _musicVolume * _masterVolume * (1.0f - Convert.ToInt32(_isMuted));
        }

        /// <summary>
        /// 将线性音量转换为分贝值
        /// </summary>
        private float ConvertToDecibel(float linearVolume)
        {
            if (linearVolume <= 0.0f)
                return -80.0f; // 静音

            // 将0-1的线性值转换为分贝值（约-80dB到0dB）
            return Mathf.Log10(linearVolume) * 20.0f;
        }

        /// <summary>
        /// 播放音乐协程
        /// </summary>
        private IEnumerator PlayMusicRoutine(string clipName, bool fadeIn)
        {
            // 加载音频剪辑
            AudioClip newClip = GetAudioClip(clipName);
            if (newClip == null)
            {
                LogWarning($"找不到音乐: {clipName}");
                yield break;
            }

            // 如果正在播放，先淡出
            if (_musicSource.isPlaying && fadeIn)
            {
                yield return StartCoroutine(FadeOutMusic());
            }

            // 设置新音乐
            _musicSource.clip = newClip;
            _currentMusic = newClip;

            // 如果需要淡入，音量从0开始
            if (fadeIn)
            {
                _musicSource.volume = 0;
            }
            else
            {
                _musicSource.volume = _musicVolume * _masterVolume * (1.0f - Convert.ToInt32(_isMuted));
            }

            // 播放音乐
            _musicSource.Play();

            Log($"播放音乐: {clipName}");

            // 淡入
            if (fadeIn)
            {
                yield return StartCoroutine(FadeInMusic());
            }
        }

        /// <summary>
        /// 淡入音乐
        /// </summary>
        private IEnumerator FadeInMusic()
        {
            float targetVolume = _musicVolume * _masterVolume * (1.0f - Convert.ToInt32(_isMuted));
            float startVolume = 0;
            float timer = 0;

            while (timer < _fadeInDuration)
            {
                timer += Time.deltaTime;
                float t = timer / _fadeInDuration;
                _musicSource.volume = Mathf.Lerp(startVolume, targetVolume, t);
                yield return null;
            }

            _musicSource.volume = targetVolume;
        }

        /// <summary>
        /// 淡出音乐
        /// </summary>
        private IEnumerator FadeOutMusic()
        {
            float startVolume = _musicSource.volume;
            float timer = 0;

            while (timer < _fadeOutDuration)
            {
                timer += Time.deltaTime;
                float t = timer / _fadeOutDuration;
                _musicSource.volume = Mathf.Lerp(startVolume, 0, t);
                yield return null;
            }

            _musicSource.volume = 0;
            _musicSource.Stop();
        }

        /// <summary>
        /// 开始淡入淡出
        /// </summary>
        private void StartFade(FadeType fadeType)
        {
            // 停止当前的淡入淡出
            if (_fadeCoroutine != null)
            {
                StopCoroutine(_fadeCoroutine);
            }

            // 开始新的淡入淡出
            if (fadeType == FadeType.In)
            {
                _fadeCoroutine = StartCoroutine(FadeInMusic());
            }
            else
            {
                _fadeCoroutine = StartCoroutine(FadeOutMusic());
            }
        }

        /// <summary>
        /// 打印调试日志
        /// </summary>
        private void Log(string message)
        {
            if (_debugMode)
            {
                Debug.Log($"[AudioManager] {message}");
            }
        }

        /// <summary>
        /// 打印警告日志
        /// </summary>
        private void LogWarning(string message)
        {
            Debug.LogWarning($"[AudioManager] {message}");
        }

        #endregion

        #region 辅助类型

        /// <summary>
        /// 淡入淡出类型
        /// </summary>
        private enum FadeType
        {
            In,
            Out
        }

        #endregion
    }
}